package com.wangxiaonan.migration.service.impl;

import com.wangxiaonan.migration.domain.Base;
import com.wangxiaonan.migration.domain.QueryResult;
import com.wangxiaonan.migration.dto.AppInfoQueryParms;
import com.wangxiaonan.migration.service.ESService;
import io.searchbox.client.JestClient;
import io.searchbox.client.JestResult;
import io.searchbox.core.Search;
import io.searchbox.core.SearchResult;
import io.searchbox.core.SearchScroll;
import io.searchbox.params.Parameters;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * @Author: wangxiaonan
 * @Date: 2018/7/17
 **/
@Service
public class ESServiceImpl implements ESService {
    private static final Logger logger = LoggerFactory.getLogger(ESServiceImpl.class);
    private static final int RESPONSE_CODE_OK = 200;
    private static final int RESPONSE_CODE_NOT_FOUND = 404;

    @Autowired
    private JestClient jestClient;

    @Override
    public <T extends Base> Page<T> searchInfo(Class<T> clazz, AppInfoQueryParms queryContent) {
        logger.info("[ESServiceImpl]==>[searchInfo] 参数：{}", queryContent);
        Page<T> collectAppInfos = null;

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        Map<String, String> queries = queryContent.getQueryContent();
        if (queries != null) {
            for (Map.Entry entry : queries.entrySet()) {
                searchSourceBuilder.query(QueryBuilders.matchQuery(entry.getKey().toString(), entry.getValue()));
            }
        }
        searchSourceBuilder.size(queryContent.getSize()).from(queryContent.getPage() * queryContent.getSize());

        if (CollectionUtils.isEmpty(queryContent.getIndices())) {
            logger.info("[ESServiceImpl ==> searchInfo] indices ===== null");
            return collectAppInfos;
        }
        Search search = new Search.Builder(searchSourceBuilder.toString()).addIndices(queryContent.getIndices()).build();
        try {
            SearchResult result = jestClient.execute(search);
            if (result != null && result.getResponseCode() == RESPONSE_CODE_OK) {
                List<T> ci = result.getSourceAsObjectList(clazz, true);
                collectAppInfos = new PageImpl<T>(ci, PageRequest.of(queryContent.getPage(), queryContent.getSize()), result.getTotal());
            } else {
                logger.info("[ESServiceImpl] SearchResult >>>>> ElasticSearch 未查到结果");
            }

        } catch (IOException e) {
            logger.error("[ESServiceImpl] search fail", e);
        }

        return collectAppInfos;
    }

    @Override
    public <T extends Base> QueryResult<T> searchInfoByScroll(Class<T> clazz, AppInfoQueryParms queryContent) {
        logger.info("[ESServiceImpl]==>[searchInfo] 参数：{}", queryContent);
        QueryResult<T> queryResult = new QueryResult<>();
        Page<T> collectAppInfos = null;

        if (StringUtils.isEmpty(queryContent.getScrollId()) || StringUtils.isEmpty(queryContent.getScroll())) {
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            Map<String, String> queries = queryContent.getQueryContent();
            if (queries != null) {
                for (Map.Entry entry : queries.entrySet()) {
                    searchSourceBuilder.query(QueryBuilders.matchQuery(entry.getKey().toString(), entry.getValue()));
                }
            }
            searchSourceBuilder.size(queryContent.getSize()).from(queryContent.getPage() * queryContent.getSize());

            if (CollectionUtils.isEmpty(queryContent.getIndices())) {
                logger.info("[ESServiceImpl ==> searchInfo] indices ===== null");
                return queryResult;
            }
            Search search = new Search.Builder(searchSourceBuilder.toString()).addIndices(queryContent.getIndices())
                    .setParameter(Parameters.SCROLL, queryContent.getScroll()).build();
            try {
                SearchResult result = jestClient.execute(search);
                if (result != null && result.getResponseCode() == RESPONSE_CODE_OK) {
                    List<T> ci = result.getSourceAsObjectList(clazz, true);
                    collectAppInfos = new PageImpl<>(ci, PageRequest.of(queryContent.getPage(), queryContent.getSize()), result.getTotal());
                    queryResult.setScrollId(result.getJsonObject().get("_scroll_id").getAsString());
                } else {
                    logger.info("[ESServiceImpl] SearchResult >>>>> ElasticSearch 未查到结果");
                }
            } catch (IOException e) {
                logger.error("[ESServiceImpl] search fail", e);
            }
        } else {
            SearchScroll scroll = new SearchScroll.Builder(queryContent.getScrollId(), queryContent.getScroll()).build();
            try {
                JestResult result = jestClient.execute(scroll);
                if (result != null && result.getResponseCode() == RESPONSE_CODE_OK) {
                    List<T> ci = result.getSourceAsObjectList(clazz, true);
                    collectAppInfos = new PageImpl<>(ci, PageRequest.of(queryContent.getPage(), queryContent.getSize()), queryContent.getTotal());
                    queryResult.setScrollId(result.getJsonObject().get("_scroll_id").getAsString());
                } else {
                    logger.info("[ESServiceImpl] SearchResult >>>>> ElasticSearch 未查到结果");
                }

            } catch (IOException e) {
                logger.error("[ESServiceImpl] search fail", e);
            }
        }

        queryResult.setPage(collectAppInfos);
        return queryResult;
    }
}
